/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.service.evaluation;

import cn.ac.nercis.pes.common.constant.common.AssetConstants;
import cn.ac.nercis.pes.common.constant.evaluation.AssetKeyDataReq;
import cn.ac.nercis.pes.common.constant.evaluation.AssetPhySecurityReq;
import cn.ac.nercis.pes.common.constant.evaluation.AssetSubBusinessReq;
import cn.ac.nercis.pes.common.constant.evaluation.EvaluationModule;
import cn.ac.nercis.pes.common.constant.knowledge.AssetClassification;
import cn.ac.nercis.pes.common.constant.project.FinishState;
import cn.ac.nercis.pes.common.constant.rules.KeyDataReqTargetRule;
import cn.ac.nercis.pes.common.constant.rules.PhySecurityReqTargetRule;
import cn.ac.nercis.pes.common.constant.rules.SubBusinessReqTargetRule;
import cn.ac.nercis.pes.model.dto.common.Result;
import cn.ac.nercis.pes.model.dto.common.ResultCode;
import cn.ac.nercis.pes.model.dto.evaluation.asset.*;
import cn.ac.nercis.pes.repository.dal.evaluation.AssetKeyDataRepository;
import cn.ac.nercis.pes.repository.dal.evaluation.AssetRepository;
import cn.ac.nercis.pes.repository.dal.evaluation.EvaluationRecordRepository;
import cn.ac.nercis.pes.repository.dal.knowledge.KmAssetClassRepository;
import cn.ac.nercis.pes.repository.dal.manage.ConstantRepository;
import cn.ac.nercis.pes.repository.dal.project.SystemRepository;
import cn.ac.nercis.pes.repository.mapper.evaluation.AssetMapper;
import cn.ac.nercis.pes.repository.model.evaluation.AssetDO;
import cn.ac.nercis.pes.repository.model.evaluation.AssetEvaluationMethodDO;
import cn.ac.nercis.pes.repository.model.evaluation.AssetKeyDataDO;
import cn.ac.nercis.pes.repository.model.knowledge.KmAssetAttributeDO;
import cn.ac.nercis.pes.repository.model.knowledge.KmAssetClassDO;
import cn.ac.nercis.pes.service.manage.ProcessRelatedService;
import cn.ac.nercis.pes.service.project.SystemProcessService;
import cn.ac.nercis.pes.service.utils.AssetUtils;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 系统资产信息服务类
 * @author zpy
 * @version 1.0.0
 */
@Slf4j
@Service
public class AssetService {
    private static final String DEFAULT_MANAGE_DOC_CONSTANT = "管理类文档_默认对象";
    private static final List<KmAssetClassDO> KM_ASSET_CLASS_CACHE = new ArrayList<>();

    private final KmAssetClassRepository kmAssetClassRepository;
    private final AssetRepository assetRepository;
    private final ConstantRepository constantRepository;
    private final EvaluationRangeService evaluationRangeService;
    private final EvaluationRecordRepository evaluationRecordRepository;
    private final ProcessRelatedService processRelatedService;
    private final AssetKeyDataRepository assetKeyDataRepository;
    private final SystemProcessService systemProcessService;
    private final AssetVariableApplyService assetVariableApplyService;
    private final SystemRepository systemRepository;

    @Autowired
    public AssetService(KmAssetClassRepository kmAssetClassRepository, AssetRepository assetRepository,
                        ConstantRepository constantRepository,EvaluationRangeService evaluationRangeService,
                        EvaluationRecordRepository evaluationRecordRepository,
                        ProcessRelatedService processRelatedService,
                        AssetKeyDataRepository assetKeyDataRepository,
                        SystemProcessService systemProcessService,
                        AssetVariableApplyService assetVariableApplyService,
                        SystemRepository systemRepository) {
        this.kmAssetClassRepository = kmAssetClassRepository;
        this.assetRepository = assetRepository;
        this.constantRepository = constantRepository;
        this.evaluationRangeService = evaluationRangeService;
        this.evaluationRecordRepository = evaluationRecordRepository;
        this.processRelatedService = processRelatedService;
        this.assetKeyDataRepository = assetKeyDataRepository;
        this.systemProcessService = systemProcessService;
        this.assetVariableApplyService = assetVariableApplyService;
        this.systemRepository = systemRepository;
    }

    public List<PhyEnvDTO> findPhyEnv(String name, String systemId){
        return this.findAssets(name,systemId, AssetClassification.PHY_ENV)
                .stream()
                .map(AssetMapper.INSTANCE::toPhyEnvDTO)
                .collect(Collectors.toList());
    }
    public Result<String> savePhyEnv(String systemId, PhyEnvDTO phyEnv){
        if(Objects.isNull(phyEnv.getIsUse())){
            phyEnv.setIsUse(false);
        }
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(phyEnv);
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.PHY_ENV.getId());
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.PHY_ENV);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(phyEnv,kmAtt))
                .collect(Collectors.toSet()));
        return saveAsset(assetDO);
    }

    public Result<String> batchSavePhyEnv(String systemId,List<PhyEnvDTO> data){
        Result<String> result = Result.success();
        for(PhyEnvDTO item : data){
            result = savePhyEnv(systemId,item);
            if(!result.isSuccess()){
                result = Result.failed(ResultCode.FAIL);
                break;
            }
        }
        return result;
    }

    public List<PhySecurityDTO> findPhySecurity(String name,String systemId){
        return this.findAssets(name,systemId,AssetClassification.PHY_SECURITY)
                .stream()
                .map(AssetMapper.INSTANCE::toPhySecurity)
                .collect(Collectors.toList());
    }
    public Result<String> savePhySecurity(String systemId,PhySecurityDTO phySecurity){
        var systemDO = this.systemRepository.findById(systemId);
        if(systemDO.isEmpty()){
            return Result.failed(ResultCode.SYSTEM_NOT_EXIST);
        }
        if(StringUtils.isBlank(phySecurity.getRequire())){
            phySecurity.setRequire(String.join(AssetConstants.KEY_DATA_REQ_SPLIT,
                    AssetPhySecurityReq.getReqNames(systemDO.get().getSecurityLevel())));
        }
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(phySecurity);
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.PHY_SECURITY.getId());
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.PHY_SECURITY);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(phySecurity,kmAtt))
                .collect(Collectors.toSet()));
        try{
            if(StringUtils.isBlank(assetDO.getId())){
                return createPhySecurity(assetDO,phySecurity.getRequire());
            }else{
                return modifyPhySecurity(assetDO,phySecurity.getRequire());
            }
        }catch (Exception ex){
            log.error("保存物理安防设施类型资产信息出错：", ex);
            return Result.failed();
        }
    }

    public Result<String> batchSavePhySecurity(String systemId,List<PhySecurityDTO> data){
        Result<String> result = Result.success();
        for(PhySecurityDTO item : data){
            result = savePhySecurity(systemId,item);
            if(!result.isSuccess()){
                result = Result.failed(ResultCode.FAIL);
                break;
            }
        }
        return result;
    }

    public List<PwdProductDTO> findPwdProduct(String name, String systemId){
        return this.findAssets(name,systemId,AssetClassification.PWD_PRODUCT)
                .stream()
                .map(AssetMapper.INSTANCE::toPwdProduct)
                .collect(Collectors.toList());
    }
    public Result<String> savePwdProduct(String systemId,PwdProductDTO pwdProduct){
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(pwdProduct);
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.PWD_PRODUCT.getId());
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.PWD_PRODUCT);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(pwdProduct,kmAtt))
                .collect(Collectors.toSet()));
        return saveAsset(assetDO);
    }
    public Result<String> batchSavePwdProduct(String systemId,List<PwdProductDTO> data){
        Result<String> result = Result.success();
        for(PwdProductDTO item : data){
            result = savePwdProduct(systemId,item);
            if(!result.isSuccess()){
                result = Result.failed(ResultCode.FAIL);
                break;
            }
        }
        return result;
    }

    public List<ServerStorageDTO> findServerStorage(String name, String systemId){
        return this.findAssets(name,systemId,AssetClassification.SERVER_STORAGE)
                .stream()
                .map(AssetMapper.INSTANCE::toServerStorage)
                .collect(Collectors.toList());
    }
    public Result<String> saveServerStorage(String systemId,ServerStorageDTO serverStorage){
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(serverStorage);
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.SERVER_STORAGE.getId());
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.SERVER_STORAGE);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(serverStorage,kmAtt))
                .collect(Collectors.toSet()));
        return saveAsset(assetDO);
    }
    public Result<String> batchSaveServerStorage(String systemId,List<ServerStorageDTO> data){
        Result<String> result = Result.success();
        for(ServerStorageDTO item : data){
            result = saveServerStorage(systemId,item);
            if(!result.isSuccess()){
                result = Result.failed(ResultCode.FAIL);
                break;
            }
        }
        return result;
    }

    public List<NetworkSecurityDTO> findNetworkSecurity(String name, String systemId){
        return this.findAssets(name,systemId,AssetClassification.NETWORK_SECURITY)
                .stream()
                .map(AssetMapper.INSTANCE::toNetworkSecurity)
                .collect(Collectors.toList());
    }
    public Result<String> saveNetworkSecurity(String systemId,NetworkSecurityDTO networkSecurity){
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(networkSecurity);
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.NETWORK_SECURITY.getId());
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.NETWORK_SECURITY);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(networkSecurity,kmAtt))
                .collect(Collectors.toSet()));
        return saveAsset(assetDO);
    }
    public Result<String> batchSaveNetworkSecurity(String systemId,List<NetworkSecurityDTO> data){
        Result<String> result = Result.success();
        for(NetworkSecurityDTO item : data){
            result = saveNetworkSecurity(systemId,item);
            if(!result.isSuccess()){
                result = Result.failed(ResultCode.FAIL);
                break;
            }
        }
        return result;
    }

    public List<DatabaseDTO> findDatabase(String name, String systemId){
        return this.findAssets(name,systemId,AssetClassification.DATABASE)
                .stream()
                .map(AssetMapper.INSTANCE::toDatabase)
                .collect(Collectors.toList());
    }
    public Result<String> saveDatabase(String systemId,DatabaseDTO database){
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(database);
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.DATABASE.getId());
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.DATABASE);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(database,kmAtt))
                .collect(Collectors.toSet()));
        return saveAsset(assetDO);
    }
    public Result<String> batchSaveDatabase(String systemId,List<DatabaseDTO> data){
        Result<String> result = Result.success();
        for(DatabaseDTO item : data){
            result = saveDatabase(systemId,item);
            if(!result.isSuccess()){
                result = Result.failed(ResultCode.FAIL);
                break;
            }
        }
        return result;
    }

    public List<KeyBusinessDTO> findKeyBusiness(String name, String systemId){
        return this.findAssets(name,systemId,AssetClassification.KEY_BUSINESS)
                .stream()
                .map(AssetMapper.INSTANCE::toKeyBusiness)
                .collect(Collectors.toList());
    }
    public Result<String> saveKeyBusiness(String systemId,KeyBusinessDTO database) {
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(database);
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.KEY_BUSINESS.getId());
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.KEY_BUSINESS);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(database,kmAtt))
                .collect(Collectors.toSet()));
        if(Objects.isNull(assetDO.getIsUse())){
            assetDO.setIsUse(false);
        }
        try {
            if (StringUtils.isBlank(assetDO.getId())) {
                return createKeyBusiness(assetDO);
            } else {
                return modifyKeyBusiness(assetDO);
            }
        } catch (Exception ex) {
            log.error("保存系统关键业务应用类型资产信息出错：", ex);
            return Result.failed();
        }
    }
    public Result<String> batchSaveKeyBusiness(String systemId,List<KeyBusinessDTO> data){
        Result<String> result = Result.success();
        for(KeyBusinessDTO item : data){
            result = saveKeyBusiness(systemId,item);
            if(!result.isSuccess()){
                result = Result.failed(ResultCode.FAIL);
                break;
            }
        }
        return result;
    }

    public List<SubBusinessDTO> findSubBusiness(String systemId,String keyBusinessId){
        if(StringUtils.isEmpty(keyBusinessId)){
            return this.findAssets(null,systemId,AssetClassification.SUB_BUSINESS)
                    .stream()
                    .map(AssetMapper.INSTANCE::toSubBusiness)
                    .collect(Collectors.toList());
        }else{
            return this.findAssets(null,systemId,AssetClassification.SUB_BUSINESS)
                    .stream()
                    .filter(a->StringUtils.equals(a.getQuoteAssetId(),keyBusinessId))
                    .map(AssetMapper.INSTANCE::toSubBusiness)
                    .collect(Collectors.toList());
        }
    }

    public Result<String> checkSubBusinessReq(@NonNull final String assetId,final String reqContent){
        SubBusinessDTO keyData = this.assetRepository.findById(assetId)
                .map(AssetMapper.INSTANCE::toSubBusiness)
                .orElse(null);
        if(Objects.isNull(keyData) || StringUtils.isBlank(reqContent)){
            return Result.success();
        }
        List<String> newTargetNames = Stream.of(StringUtils.split(reqContent,AssetConstants.KEY_DATA_REQ_SPLIT))
                .map(SubBusinessReqTargetRule::fromName)
                .filter(Objects::nonNull)
                .flatMap(rt->rt.getTargetNames().stream())
                .toList();
        List<String> deleteTargetNames;
        if(StringUtils.isBlank(keyData.getRequire())){
            deleteTargetNames = Stream.of(SubBusinessReqTargetRule.values())
                    .flatMap(rt->rt.getTargetNames().stream())
                    .filter(name->newTargetNames.stream().noneMatch(tn->StringUtils.equals(tn,name)))
                    .collect(Collectors.toList());
        }else{
            deleteTargetNames = Stream.of(StringUtils.split(keyData.getRequire(), AssetConstants.KEY_DATA_REQ_SPLIT))
                    .map(SubBusinessReqTargetRule::fromName)
                    .filter(Objects::nonNull)
                    .flatMap(rt->rt.getTargetNames().stream())
                    .filter(name->newTargetNames.stream().noneMatch(tn->StringUtils.equals(tn,name)))
                    .collect(Collectors.toList());
        }
        if(CollectionUtils.isEmpty(deleteTargetNames)){
            return Result.success();
        }
        //获取将要移除的关联单元指标
        Set<String> evaluationMethodIds = evaluationRangeService.findSubBusinessEvalMethod(assetId,deleteTargetNames)
                .stream()
                .map(AssetEvaluationMethodDO::getId)
                .collect(Collectors.toSet());
        boolean hasRelated = CollectionUtils.isNotEmpty(evaluationRecordRepository.findAllByAssetEvaMethodIdIn(evaluationMethodIds));
        if(hasRelated){
            return Result.failed("当前对象将要移除的安全需求关联的指标下存在测评数据，是否继续进行保存？");
        }else {
            return Result.success();
        }
    }

    public Result<String> saveSubBusiness(String systemId,String keyBusinessId,SubBusinessDTO data){
        var systemDO = this.systemRepository.findById(systemId);
        if(systemDO.isEmpty()){
            return Result.failed(ResultCode.SYSTEM_NOT_EXIST);
        }
        if(StringUtils.isBlank(data.getRequire())){
            data.setRequire(String.join(AssetConstants.KEY_DATA_REQ_SPLIT,
                    AssetSubBusinessReq.getReqNames(systemDO.get().getSecurityLevel())));
        }
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(data);
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.SUB_BUSINESS.getId());
        assetDO.setQuoteAssetId(keyBusinessId);
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.SUB_BUSINESS);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(data,kmAtt))
                .collect(Collectors.toSet()));
        try{
            if(StringUtils.isBlank(assetDO.getId())){
                return createSubBusiness(assetDO,data.getRequire());
            }else{
                return modifySubBusiness(assetDO,data.getRequire());
            }
        }catch (Exception ex){
            log.error("保存系统子对象(关键业务应用)类型资产信息出错：", ex);
            return Result.failed();
        }
    }

    public Result<String> batchSaveSubBusiness(String systemId,String keyBusinessId,List<SubBusinessDTO> data){
        Result<String> result = Result.success();
        for(SubBusinessDTO item : data){
            result = saveSubBusiness(systemId,keyBusinessId,item);
            if(!result.isSuccess()){
                break;
            }
        }
        return result;
    }

    public List<KeyDataDTO> findKeyData(String name,String systemId){
        return this.findAssets(name,systemId,AssetClassification.KEY_DATA)
                .stream()
                .map(AssetMapper.INSTANCE::toKeyData)
                .collect(Collectors.toList());
    }

    public Result<String> checkKeyDataReq(@NonNull final String assetId,final String reqContent){
        KeyDataDTO keyData = this.assetRepository.findById(assetId)
                .map(AssetMapper.INSTANCE::toKeyData)
                .orElse(null);
        if(Objects.isNull(keyData) || StringUtils.isBlank(reqContent)){
            return Result.success();
        }
        List<String> newTargetNames = Stream.of(StringUtils.split(reqContent,AssetConstants.KEY_DATA_REQ_SPLIT))
                .map(KeyDataReqTargetRule::fromName)
                .filter(Objects::nonNull)
                .flatMap(rt->rt.getTargetNames().stream())
                .collect(Collectors.toList());
        List<String> deleteTargetNames;
        if(StringUtils.isBlank(keyData.getRequire())){
            deleteTargetNames = Stream.of(KeyDataReqTargetRule.values())
                    .flatMap(rt->rt.getTargetNames().stream())
                    .filter(name->newTargetNames.stream().noneMatch(tn->StringUtils.equals(tn,name)))
                    .collect(Collectors.toList());
        }else{
            deleteTargetNames = Stream.of(StringUtils.split(keyData.getRequire(), AssetConstants.KEY_DATA_REQ_SPLIT))
                    .map(KeyDataReqTargetRule::fromName)
                    .filter(Objects::nonNull)
                    .flatMap(rt->rt.getTargetNames().stream())
                    .filter(name->newTargetNames.stream().noneMatch(tn->StringUtils.equals(tn,name)))
                    .collect(Collectors.toList());
        }
        if(CollectionUtils.isEmpty(deleteTargetNames)){
            return Result.success();
        }
        //获取将要移除的关联单元指标
        Set<String> evaluationMethodIds = evaluationRangeService.findKeyDataEvalMethod(assetId,deleteTargetNames)
                .stream()
                .map(AssetEvaluationMethodDO::getId)
                .collect(Collectors.toSet());
        boolean hasRelated = CollectionUtils.isNotEmpty(evaluationRecordRepository.findAllByAssetEvaMethodIdIn(evaluationMethodIds));
        if(hasRelated){
            return Result.failed("当前对象将要移除的安全需求关联的指标下存在测评数据，是否继续进行保存？");
        }else {
            return Result.success();
        }
    }

    public Result<String> saveKeyData(String systemId,KeyDataDTO keyData){
        var systemDO = this.systemRepository.findById(systemId);
        if(systemDO.isEmpty()){
            return Result.failed(ResultCode.SYSTEM_NOT_EXIST);
        }
        if(StringUtils.isBlank(keyData.getRequire())){
            keyData.setRequire(String.join(AssetConstants.KEY_DATA_REQ_SPLIT,
                    AssetKeyDataReq.getReqNames(systemDO.get().getSecurityLevel())));
        }
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(keyData);
        assetDO.setName(keyData.getData());
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.KEY_DATA.getId());
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.KEY_DATA);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(keyData,kmAtt))
                .collect(Collectors.toSet()));
        try{
            if(StringUtils.isBlank(assetDO.getId())){
                return createKeyData(assetDO,keyData.getRequire());
            }else{
                return modifyKeyData(assetDO,keyData.getRequire());
            }
        }catch (Exception ex){
            log.error("保存系统重要数据类型资产信息出错：",ex);
            return Result.failed();
        }
    }

    public Result<String> batchSaveKeyData(String systemId,List<KeyDataDTO> data){
        Result<String> result = Result.success();
        for(KeyDataDTO item : data){
            result = saveKeyData(systemId,item);
            if(!result.isSuccess()){
                break;
            }
        }
        return result;
    }

    public List<ChannelDTO> findChannel(String name, String systemId){
        return this.findAssets(name,systemId,AssetClassification.COMMUNICATION_CHANNEL)
                .stream()
                .map(AssetMapper.INSTANCE::toChannel)
                .collect(Collectors.toList());
    }
    public Result<String> saveChannel(String systemId,ChannelDTO channel){
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(channel);
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.COMMUNICATION_CHANNEL.getId());
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.COMMUNICATION_CHANNEL);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(channel,kmAtt))
                .collect(Collectors.toSet()));
        return saveAsset(assetDO);
    }
    public Result<String> batchSaveChannel(String systemId,List<ChannelDTO> data){
        Result<String> result = Result.success();
        for(ChannelDTO item : data){
            result = saveChannel(systemId,item);
            if(!result.isSuccess()){
                break;
            }
        }
        return result;
    }

    public List<ManageDocumentDTO> findManageDocument(String name, String systemId){
        return this.findAssets(name,systemId,AssetClassification.MANAGE_DOC)
                .stream()
                .map(AssetMapper.INSTANCE::toManageDocument)
                .collect(Collectors.toList());
    }
    public Result<String> saveManageDocument(String systemId,ManageDocumentDTO manageDocument){
        AssetDO assetDO = AssetMapper.INSTANCE.toDO(manageDocument);
        assetDO.setSystemId(systemId);
        assetDO.setClassId(AssetClassification.MANAGE_DOC.getId());
        KmAssetClassDO assetClassDO = findKmAssetClass(AssetClassification.MANAGE_DOC);
        assetDO.setAttributes(assetClassDO.getAttributes()
                .stream()
                .map(kmAtt-> AssetUtils.toAttribute(manageDocument,kmAtt))
                .collect(Collectors.toSet()));
        return saveAsset(assetDO);
    }
    public Result<String> batchSaveManageDocument(String systemId,List<ManageDocumentDTO> data){
        Result<String> result = Result.success();
        for(ManageDocumentDTO item : data){
            result = saveManageDocument(systemId,item);
            if(!result.isSuccess()){
                break;
            }
        }
        return result;
    }

    public Result<String> checkAssetEvalRecord(@NonNull String systemId,@NonNull String assetId){
        boolean existRecord = evaluationRecordRepository.existsBySystemIdAndAsset(systemId,
                AssetDO.builder().id(assetId).build());
        if(existRecord){
            return Result.failed("当前资产对象存在测评数据，是否继续进行删除？");
        }else{
            return Result.success();
        }
    }

    public Result<String> batchCheckAssetEvalRecord(@NonNull String systemId,Set<String> assetIds){
        Result<String> result = Result.success();
        for(String id : assetIds){
            Result<String> itemResult = checkAssetEvalRecord(systemId,id);
            if(!itemResult.isSuccess()){
                result = itemResult;
                break;
            }
        }
        return result;
    }

    public Result<String> checkKeyBusinessEvalRecord(@NonNull String systemId,@NonNull String keyBusinessId){
        List<AssetDO> subKeyBusiness = this.assetRepository.findAllBySystemIdAndQuoteAssetId(systemId,keyBusinessId);
        boolean existRecord = false;
        for(AssetDO subItem : subKeyBusiness){
            existRecord = evaluationRecordRepository.existsBySystemIdAndAsset(systemId,subItem);
            if(existRecord){
                break;
            }
        }
        if(existRecord){
            return Result.failed("当前关键业务应用对象存在测评数据，是否继续进行删除？");
        }else{
            return Result.success();
        }
    }

    public Result<String> batchCheckKeyBusinessEvalRecord(@NonNull String systemId,Set<String> keyBusinessIds){
        Result<String> result = Result.success();
        for(String id : keyBusinessIds){
            Result<String> itemResult = checkKeyBusinessEvalRecord(systemId,id);
            if(!itemResult.isSuccess()){
                result = itemResult;
                break;
            }
        }
        return result;
    }

    public Result<String> deleteAsset(String id){
        try{
            return this.assetRepository.findById(id)
                    .map(assetDO -> {
                        removeAssetRef(assetDO);
                        processRelatedService.resetAssetEvalRelateModuleProcess(assetDO);
                        processRelatedService.deleteAssetRelatedData(assetDO);
                        assetRepository.delete(assetDO);
                        return assetDO;
                    })
                    .map(AssetDO::getId)
                    .map(Result::success)
                    .orElse(Result.failed());
        }catch (Exception ex){
            log.error("删除系统资产信息出错：",ex);
            return Result.failed();
        }
    }

    public Result<String> batchDeleteAsset(Set<String> ids){
        Result<String> result = Result.success();
        for(String id : ids){
            Result<String> itemResult = deleteAsset(id);
            if(!itemResult.isSuccess()){
                result = Result.failed(ResultCode.FAIL);
                break;
            }
        }
        return result;
    }

    public Result<String> deleteSubKeyBusiness(String keyBusinessId){
        AssetDO keyBusiness = this.assetRepository.findById(keyBusinessId).orElse(null);
        if(Objects.isNull(keyBusiness)){
            return Result.failed(ResultCode.ASSET_NOT_EXIST);
        }
        List<AssetDO> subKeyBusiness = this.assetRepository.findAllBySystemIdAndQuoteAssetId(keyBusiness.getSystemId(),keyBusinessId);
        Result<String> result = Result.success();
        for(AssetDO asset : subKeyBusiness){
            Result<String> itemResult = deleteAsset(asset.getId());
            if(!itemResult.isSuccess()){
                result = Result.failed(String.format("删除(%s)子对象失败",asset.getName()));
            }
        }
        if(!result.isSuccess()){
            return result;
        }
        return deleteAsset(keyBusinessId);
    }

    public Result<String> batchDeleteSubKeyBusiness(Set<String> ids){
        Result<String> result = Result.success();
        for(String id : ids){
            Result<String> itemResult = deleteSubKeyBusiness(id);
            if(!itemResult.isSuccess()){
                result = itemResult;
                break;
            }
        }
        return result;
    }

    public void generateDefaultSystemAsset(String systemId){
        constantRepository.findAllByNameOrderBySort(DEFAULT_MANAGE_DOC_CONSTANT)
                .stream()
                .map(constantDO->ManageDocumentDTO.builder()
                        .name(constantDO.getValue())
                        .isUse(true)
                        .build())
                .forEach(manageDocumentDTO -> saveManageDocument(systemId,manageDocumentDTO));
    }

    public KmAssetClassDO findKmAssetClass(AssetClassification assetClass){
        if(KM_ASSET_CLASS_CACHE.size()==0){
            KM_ASSET_CLASS_CACHE.addAll(this.kmAssetClassRepository.findAll());
        }
        return KM_ASSET_CLASS_CACHE.stream()
                .filter(ac->StringUtils.equals(assetClass.getId(),ac.getId()))
                .findFirst()
                .orElseThrow(()->new RuntimeException(String.format("资产分类（ID：%s，Name：%s）从数据表中未找到",
                        assetClass.getId(),assetClass.getName())));
    }

    public Result<String> saveAsset(@NonNull AssetDO assetDO){
        try{
            if(StringUtils.isBlank(assetDO.getId())){
                return createAsset(assetDO);
            }else{
                return modifyAsset(assetDO,true);
            }
        }catch (Exception ex){
            log.error("保存系统资产信息出错：",ex);
            return Result.failed();
        }
    }

    private List<AssetDO> findAssets(String name,String systemId,AssetClassification assetClass){
        List<AssetDO> assets = assetRepository.findAllBySystemIdAndClassId(systemId, assetClass.getId());
        if(StringUtils.isBlank(name)){
            return assets;
        }
        return assets.stream().filter(a->assetFilter(a,name)).collect(Collectors.toList());
    }

    private boolean assetFilter(AssetDO assetDO,String name){
        if(CollectionUtils.isEmpty(assetDO.getAttributes())){
            return false;
        }
        return assetDO.getAttributes()
                .stream()
                .anyMatch(att-> StringUtils.contains(att.getValue(),name));
    }

    private void refreshAssetRef(@NonNull AssetDO source,String oldContent,String newContent){
        List<AssetDO> assetDOS = assetRepository.findAllBySystemId(source.getSystemId())
                .stream()
                .filter(a->StringUtils.isNotEmpty(a.getQuoteAssetId()) && StringUtils.contains(a.getQuoteAssetId(),source.getId()))
                .collect(Collectors.toList());
        if(CollectionUtils.isEmpty(assetDOS)){
            return;
        }
        List<KmAssetClassDO> kmAssetClassDOS = kmAssetClassRepository.findAll();
        refreshAssetRef(source,assetDOS,kmAssetClassDOS,oldContent,newContent);
        refreshAssetRefByAssetKeyData(source,newContent);
    }

    private void refreshAssetRef(@NonNull AssetDO source,List<AssetDO> rebootAssets,List<KmAssetClassDO> kmAssetClassDOS,String oldContent,String newContent){
        KmAssetAttributeDO nameAttribute = kmAssetClassDOS.stream()
                .filter(ac->StringUtils.equals(ac.getId(),source.getClassId()))
                .flatMap(ac->ac.getAttributes().stream())
                .filter(KmAssetAttributeDO::getIsName)
                .findFirst()
                .orElse(null);
        if(Objects.isNull(nameAttribute)){
            return;
        }
        rebootAssets.forEach(asset->kmAssetClassDOS.stream()
                .filter(ac->StringUtils.equals(ac.getId(),asset.getClassId()))
                .flatMap(ac->ac.getAttributes().stream())
                .filter(aa->StringUtils.equals(aa.getRefId(),nameAttribute.getId()))
                .findFirst()
                .ifPresent(aa->{
                    asset.getAttributes()
                            .stream()
                            .filter(att->StringUtils.equals(att.getAttributeId(),aa.getId()))
                            .forEach(att-> att.setValue(StringUtils.replace(att.getValue(),oldContent,newContent)));
                    modifyAsset(asset,false);
                }));
    }

    public void refreshAssetRefByAssetKeyData(@NonNull AssetDO source,@NonNull String assetName){
        List<AssetKeyDataDO> assetKeyDataDOS = this.assetKeyDataRepository.findAllBySystemId(source.getSystemId())
                .stream()
                .filter(kd->StringUtils.equals(kd.getLocationAssetId(),source.getId()) || StringUtils.equals(kd.getOwnedAppAssetId(),source.getId()))
                .peek(kd->{
                    if(StringUtils.equals(kd.getOwnedAppAssetId(),source.getId())){
                        kd.setOwnedApp(assetName);
                    }
                    if(StringUtils.equals(kd.getLocationAssetId(),source.getId())){
                        kd.setLocation(assetName);
                    }
                })
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(assetKeyDataDOS)){
            this.assetKeyDataRepository.saveAllAndFlush(assetKeyDataDOS);
        }
    }

    private void removeAssetRef(@NonNull AssetDO source){
        List<AssetDO> assetDOS = assetRepository.findAllBySystemId(source.getSystemId())
                .stream()
                .filter(a->StringUtils.isNotEmpty(a.getQuoteAssetId()) && StringUtils.contains(a.getQuoteAssetId(),source.getId()))
                .collect(Collectors.toList());
        if(CollectionUtils.isEmpty(assetDOS)){
            return;
        }
        List<KmAssetClassDO> kmAssetClassDOS = kmAssetClassRepository.findAll();
        removeAssetRef(source,assetDOS,kmAssetClassDOS);
        removeAssetRefByAssetKeyData(source);
    }

    private void removeAssetRef(@NonNull AssetDO source,List<AssetDO> rebootAssets,List<KmAssetClassDO> kmAssetClassDOS){
        KmAssetAttributeDO nameAttribute = kmAssetClassDOS.stream()
                .filter(ac->StringUtils.equals(ac.getId(),source.getClassId()))
                .flatMap(ac->ac.getAttributes().stream())
                .filter(KmAssetAttributeDO::getIsName)
                .findFirst()
                .orElse(null);
        if(Objects.isNull(nameAttribute)){
            return;
        }
        rebootAssets.forEach(asset->kmAssetClassDOS.stream()
                .filter(ac->StringUtils.equals(ac.getId(),asset.getClassId()))
                .flatMap(ac->ac.getAttributes().stream())
                .filter(aa->StringUtils.equals(aa.getRefId(),nameAttribute.getId()))
                .findFirst()
                .ifPresent(aa->{
                    asset.getAttributes()
                            .stream()
                            .filter(att->StringUtils.equals(att.getAttributeId(),aa.getId()))
                            .forEach(att-> att.setValue(StringUtils.replace(att.getValue(),source.getName(),StringUtils.EMPTY)));
                    modifyAsset(asset,false);
                }));
        rebootAssets.stream()
                .map(a->assetClassToModule(a.getClassId()))
                .filter(Objects::nonNull)
                .distinct()
                .forEach(module-> this.systemProcessService.setSystemProcess(source.getSystemId(),module, FinishState.INCOMPLETE));
    }

    private void removeAssetRefByAssetKeyData(@NonNull AssetDO source){
        List<AssetKeyDataDO> assetKeyDataDOS = this.assetKeyDataRepository.findAllBySystemId(source.getSystemId())
                .stream()
                .filter(kd->StringUtils.equals(kd.getLocationAssetId(),source.getId()) || StringUtils.equals(kd.getOwnedAppAssetId(),source.getId()))
                .peek(kd->{
                    if(StringUtils.equals(kd.getOwnedAppAssetId(),source.getId())){
                        kd.setOwnedApp(StringUtils.EMPTY);
                    }
                    if(StringUtils.equals(kd.getLocationAssetId(),source.getId())){
                        kd.setLocation(StringUtils.EMPTY);
                    }
                })
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(assetKeyDataDOS)){
            this.assetKeyDataRepository.saveAllAndFlush(assetKeyDataDOS);
            this.systemProcessService.setSystemProcess(source.getSystemId(), EvaluationModule.ASSET_KEY_DATA,FinishState.INCOMPLETE);
        }
    }

    private EvaluationModule assetClassToModule(String classId){
        AssetClassification ac = AssetClassification.fromId(classId);
        if(Objects.isNull(ac)){
            return null;
        }
        if(ac==AssetClassification.MANAGE_DOC){
            return EvaluationModule.ASSET_SECURITY_DOC;
        }else{
            return EvaluationModule.fromNameBySystemAsset(ac.getName());
        }
    }

    private Result<String> createAsset(@NonNull AssetDO assetDO){
        assetDO.setCreateTime(LocalDateTime.now());
        assetDO.getAttributes().forEach(att->{
            att.setAsset(assetDO);
            att.setCreateTime(LocalDateTime.now());
        });
        return Optional.of(this.assetRepository.save(assetDO))
                .map(a->{
                    if(assetDO.getIsUse()){
                        //测评情况下，创建资产默认关联指标
                        evaluationRangeService.generateDefaultEvalMethod(a);
                    }
                    return a.getId();
                })
                .map(Result::success)
                .orElse(Result.failed());
    }

    private Result<String> modifyAsset(@NonNull AssetDO assetDO,boolean processIsUseChange){
        AssetDO source = this.assetRepository.findById(assetDO.getId()).orElse(null);
        if(Objects.isNull(source)){
            return Result.failed(ResultCode.NOT_FOUND);
        }
        if(!StringUtils.equals(source.getName(),assetDO.getName())){
            refreshAssetRef(source,source.getName(),assetDO.getName());
            source.setName(assetDO.getName());
        }
        if(processIsUseChange){
            assetIsUseChange(source,assetDO);
        }
        source.setDesc(assetDO.getDesc());
        source.setQuoteAssetId(assetDO.getQuoteAssetId());
        source.setModifyTime(LocalDateTime.now());
        source.setIsUse(assetDO.getIsUse());
        source.getAttributes().forEach(attr-> assetDO.getAttributes()
                .stream()
                .filter(a -> StringUtils.equals(attr.getAttributeId(), a.getAttributeId()))
                .findFirst()
                .ifPresent(a -> {
                    attr.setValue(a.getValue());
                    attr.setModifyTime(LocalDateTime.now());
                }));
        assetDO.getAttributes().forEach(attr->{
            var notExist =source.getAttributes()
                    .stream()
                    .noneMatch(a -> StringUtils.equals(attr.getAttributeId(), a.getAttributeId()));
            if(notExist){
                attr.setCreateTime(LocalDateTime.now());
                attr.setAsset(source);
                source.getAttributes().add(attr);
            }
        });
        AssetDO oldAsset = this.assetRepository.findById(assetDO.getId()).orElse(null);
        this.assetRepository.save(source);
        if(Objects.nonNull(oldAsset)){
            assetVariableApplyService.assetVariableSync(oldAsset,source, this);
        }
        return Result.success(source.getId());
    }

    private void assetIsUseChange(AssetDO source,AssetDO newAsset){
        if(source.getIsUse() && (!newAsset.getIsUse())){
            //是否测评变更为否情况下，移除关联的指标与测评记录
            processRelatedService.resetAssetEvalRelateModuleProcess(source);
            processRelatedService.deleteAssetRelatedData(source);
        }else if(newAsset.getIsUse() && (!source.getIsUse())){
            //是否测评变更为是情况下，添加关联的指标与测评记录
            evaluationRangeService.generateDefaultEvalMethod(newAsset);
        }
    }

    private Result<String> createPhySecurity(@NonNull AssetDO assetDO, String reqContent) {
        assetDO.setCreateTime(LocalDateTime.now());
        assetDO.getAttributes().forEach(att -> {
            att.setAsset(assetDO);
            att.setCreateTime(LocalDateTime.now());
        });
        return Optional.of(this.assetRepository.save(assetDO))
                .map(a -> {
                    if(assetDO.getIsUse()){
                        //测评情况下，创建物理安防设施默认关联指标
                        evaluationRangeService.generatePhySecurityEvalMethod(a,reqContent);
                    }
                    return a.getId();
                })
                .map(Result::success)
                .orElse(Result.failed());
    }

    private Result<String> modifyPhySecurity(@NonNull AssetDO assetDO,String reqContent){
        AssetDO source = this.assetRepository.findById(assetDO.getId()).orElse(null);
        if(Objects.isNull(source)){
            return Result.failed(ResultCode.NOT_FOUND);
        }
        String oldReqContent = AssetMapper.INSTANCE.toPhySecurity(source).getRequire();
        if(source.getIsUse() && assetDO.getIsUse() && !StringUtils.equals(oldReqContent,reqContent)){
            modifyPhySecurityReq(assetDO,oldReqContent,reqContent);
        }
        this.assetIsUseChangeByPhySecurity(source,assetDO,reqContent);
        return modifyAsset(assetDO,false);
    }

    private void assetIsUseChangeByPhySecurity(AssetDO source,AssetDO newAsset,String reqContent){
        if(source.getIsUse() && (!newAsset.getIsUse())){
            //是否测评变更为否情况下，移除关联的指标与测评记录
            processRelatedService.resetAssetEvalRelateModuleProcess(source);
            processRelatedService.deleteAssetRelatedData(source);
        }else if(newAsset.getIsUse() && (!source.getIsUse())){
            //是否测评变更为是情况下，创建物理安防设施默认关联指标
            evaluationRangeService.generatePhySecurityEvalMethod(source,reqContent);
        }
    }

    private void modifyPhySecurityReq(@NonNull AssetDO assetDO,String oldReqContent,String newReqContent){
        if(StringUtils.isBlank(oldReqContent) && StringUtils.isBlank(newReqContent)){
            return;
        }
        List<String> newTargetNames = this.getPhySecurityReqTargetNames(newReqContent);
        List<String> sourceTargetNames = this.getPhySecurityReqTargetNames(oldReqContent);
        List<String> deleteTargetNames = sourceTargetNames.stream()
                .filter(name->newTargetNames.stream().noneMatch(tn->StringUtils.equals(tn,name)))
                .collect(Collectors.toList());
        List<String> addTargetNames = newTargetNames.stream()
                .filter(name->sourceTargetNames.stream().noneMatch(tn->StringUtils.equals(tn,name)))
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(deleteTargetNames)){
            processRelatedService.deleteAssetRelatedData(evaluationRangeService.findPhySecurityEvalMethod(assetDO.getId(),deleteTargetNames));
        }
        if(CollectionUtils.isNotEmpty(addTargetNames)){
            evaluationRangeService.modifyPhySecurityEvalMethod(assetDO,addTargetNames);
        }
    }

    private Result<String> createKeyBusiness(@NonNull AssetDO assetDO) {
        assetDO.setCreateTime(LocalDateTime.now());
        assetDO.getAttributes().forEach(att -> {
            att.setAsset(assetDO);
            att.setCreateTime(LocalDateTime.now());
        });
        String defaultRequire = Stream.of(AssetSubBusinessReq.ACCESS_INTEGRITY, AssetSubBusinessReq.IMPORTANT_INTEGRITY,
                        AssetSubBusinessReq.NON_REPUDIATION)
                .map(AssetSubBusinessReq::getName)
                .collect(Collectors.joining(AssetConstants.KEY_DATA_REQ_SPLIT));
        return Optional.of(this.assetRepository.save(assetDO))
                .map(a -> {
                    if(assetDO.getIsUse()){
                        //测评情况下，创建资产默认关联指标
                        evaluationRangeService.generateDefaultEvalMethod(a);
                    }
                    //创建默认子对象
                    SubBusinessDTO subBusinessDTO = SubBusinessDTO.builder()
                            .name(a.getName())
                            .ownedApp(a.getName())
                            .require(defaultRequire)
                            .quoteAssetId(a.getId())
                            .isUse(true)
                            .build();
                    this.saveSubBusiness(a.getSystemId(),a.getId() ,subBusinessDTO);
                    return a.getId();
                })
                .map(Result::success)
                .orElse(Result.failed());
    }

    private Result<String> modifyKeyBusiness(@NonNull AssetDO assetDO) {
        AssetDO source = this.assetRepository.findById(assetDO.getId()).orElse(null);
        if (Objects.isNull(source)) {
            return Result.failed(ResultCode.NOT_FOUND);
        }
        if (!StringUtils.equals(assetDO.getName(), source.getName())) {
            modifySubBusinessName(source, source.getName(), assetDO.getName());
        }
        return modifyAsset(assetDO,true);
    }

    private void modifySubBusinessName(AssetDO keyBusiness, String oldName, String newName) {
        this.findSubBusiness(keyBusiness.getSystemId(), keyBusiness.getId())
                .forEach(data -> {
                    if(StringUtils.equals(data.getName(),oldName)){
                        data.setName(newName);
                    }
                    data.setOwnedApp(newName);
                    this.saveSubBusiness(keyBusiness.getSystemId(),keyBusiness.getId(), data);
                });
    }

    private Result<String> createSubBusiness(@NonNull AssetDO assetDO, String reqContent) {
        assetDO.setCreateTime(LocalDateTime.now());
        assetDO.getAttributes().forEach(att -> {
            att.setAsset(assetDO);
            att.setCreateTime(LocalDateTime.now());
        });
        return Optional.of(this.assetRepository.save(assetDO))
                .map(a -> {
                    if(assetDO.getIsUse()){
                        //测评情况下，创建重要数据资产默认关联指标
                        evaluationRangeService.generateSubBusinessEvalMethod(a,reqContent);
                    }
                    return a.getId();
                })
                .map(Result::success)
                .orElse(Result.failed());
    }

    private Result<String> modifySubBusiness(@NonNull AssetDO assetDO,String reqContent){
        AssetDO source = this.assetRepository.findById(assetDO.getId()).orElse(null);
        if(Objects.isNull(source)){
            return Result.failed(ResultCode.NOT_FOUND);
        }
        String oldReqContent = AssetMapper.INSTANCE.toSubBusiness(source).getRequire();
        if(source.getIsUse() && assetDO.getIsUse() && !StringUtils.equals(oldReqContent,reqContent)){
            modifySubBusinessReq(assetDO,oldReqContent,reqContent);
        }
        this.assetIsUseChangeBySubBusiness(source,assetDO,reqContent);
        return modifyAsset(assetDO,false);
    }

    private void assetIsUseChangeBySubBusiness(AssetDO source,AssetDO newAsset,String reqContent){
        if(source.getIsUse() && (!newAsset.getIsUse())){
            //是否测评变更为否情况下，移除关联的指标与测评记录
            processRelatedService.resetAssetEvalRelateModuleProcess(source);
            processRelatedService.deleteAssetRelatedData(source);
        }else if(newAsset.getIsUse() && (!source.getIsUse())){
            //是否测评变更为是情况下，创建重要数据资产默认关联指标
            evaluationRangeService.generateSubBusinessEvalMethod(source,reqContent);
        }
    }

    private void modifySubBusinessReq(@NonNull AssetDO assetDO,String oldReqContent,String newReqContent){
        if(StringUtils.isBlank(oldReqContent) && StringUtils.isBlank(newReqContent)){
            return;
        }
        List<String> newTargetNames = this.getSubBusinessReqTargetNames(newReqContent);
        List<String> sourceTargetNames = this.getSubBusinessReqTargetNames(oldReqContent);
        List<String> deleteTargetNames = sourceTargetNames.stream()
                .filter(name->newTargetNames.stream().noneMatch(tn->StringUtils.equals(tn,name)))
                .collect(Collectors.toList());
        List<String> addTargetNames = newTargetNames.stream()
                .filter(name->sourceTargetNames.stream().noneMatch(tn->StringUtils.equals(tn,name)))
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(deleteTargetNames)){
            processRelatedService.deleteAssetRelatedData(evaluationRangeService.findSubBusinessEvalMethod(assetDO.getId(),deleteTargetNames));
        }
        if(CollectionUtils.isNotEmpty(addTargetNames)){
            evaluationRangeService.modifySubBusinessEvalMethod(assetDO,addTargetNames);
        }
    }

    private Result<String> createKeyData(@NonNull AssetDO assetDO,String reqContent){
        assetDO.setCreateTime(LocalDateTime.now());
        assetDO.getAttributes().forEach(att->{
            att.setAsset(assetDO);
            att.setCreateTime(LocalDateTime.now());
        });
        return Optional.of(this.assetRepository.save(assetDO))
                .map(a->{
                    if(assetDO.getIsUse()){
                        //测评情况下，创建重要数据资产默认关联指标
                        evaluationRangeService.generateKeyDataEvalMethod(a,reqContent);
                    }
                    return a.getId();
                })
                .map(Result::success)
                .orElse(Result.failed());
    }

    private Result<String> modifyKeyData(@NonNull AssetDO assetDO,String reqContent){
        AssetDO source = this.assetRepository.findById(assetDO.getId()).orElse(null);
        if(Objects.isNull(source)){
            return Result.failed(ResultCode.NOT_FOUND);
        }
        String oldReqContent = AssetMapper.INSTANCE.toKeyData(source).getRequire();
        if(source.getIsUse() && assetDO.getIsUse() && !StringUtils.equals(oldReqContent,reqContent)){
            modifyKeyDataReq(assetDO,oldReqContent,reqContent);
        }
        this.assetIsUseChangeByKeyData(source,assetDO,reqContent);
        return modifyAsset(assetDO,false);
    }

    private void assetIsUseChangeByKeyData(AssetDO source,AssetDO newAsset,String reqContent){
        if(source.getIsUse() && (!newAsset.getIsUse())){
            //是否测评变更为否情况下，移除关联的指标与测评记录
            processRelatedService.resetAssetEvalRelateModuleProcess(source);
            processRelatedService.deleteAssetRelatedData(source);
        }else if(newAsset.getIsUse() && (!source.getIsUse())){
            //是否测评变更为是情况下，创建重要数据资产默认关联指标
            evaluationRangeService.generateKeyDataEvalMethod(source,reqContent);
        }
    }

    private void modifyKeyDataReq(@NonNull AssetDO assetDO,String oldReqContent,String newReqContent){
        if(StringUtils.isBlank(oldReqContent) && StringUtils.isBlank(newReqContent)){
            return;
        }
        List<String> newTargetNames = this.getKeyDataReqTargetNames(newReqContent);
        List<String> sourceTargetNames = this.getKeyDataReqTargetNames(oldReqContent);
        List<String> deleteTargetNames = sourceTargetNames.stream()
                .filter(name->newTargetNames.stream().noneMatch(tn->StringUtils.equals(tn,name)))
                .collect(Collectors.toList());
        List<String> addTargetNames = newTargetNames.stream()
                .filter(name->sourceTargetNames.stream().noneMatch(tn->StringUtils.equals(tn,name)))
                .collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(deleteTargetNames)){
            processRelatedService.deleteAssetRelatedData(evaluationRangeService.findKeyDataEvalMethod(assetDO.getId(),deleteTargetNames));
        }
        if(CollectionUtils.isNotEmpty(addTargetNames)){
            evaluationRangeService.modifyKeyDataEvalMethod(assetDO,addTargetNames);
        }
    }

    private List<String> getPhySecurityReqTargetNames(String reqContent){
        if(StringUtils.isBlank(reqContent)){
            return Stream.of(PhySecurityReqTargetRule.values())
                    .flatMap(rt->rt.getTargetNames().stream())
                    .collect(Collectors.toList());
        }else{
            return Stream.of(StringUtils.split(reqContent, AssetConstants.KEY_DATA_REQ_SPLIT))
                    .map(PhySecurityReqTargetRule::fromName)
                    .filter(Objects::nonNull)
                    .flatMap(rt->rt.getTargetNames().stream())
                    .collect(Collectors.toList());
        }
    }

    private List<String> getSubBusinessReqTargetNames(String reqContent){
        if(StringUtils.isBlank(reqContent)){
            return Stream.of(SubBusinessReqTargetRule.values())
                    .flatMap(rt->rt.getTargetNames().stream())
                    .collect(Collectors.toList());
        }else{
            return Stream.of(StringUtils.split(reqContent, AssetConstants.KEY_DATA_REQ_SPLIT))
                    .map(SubBusinessReqTargetRule::fromName)
                    .filter(Objects::nonNull)
                    .flatMap(rt->rt.getTargetNames().stream())
                    .collect(Collectors.toList());
        }
    }

    private List<String> getKeyDataReqTargetNames(String reqContent){
        if(StringUtils.isBlank(reqContent)){
            return Stream.of(KeyDataReqTargetRule.values())
                    .flatMap(rt->rt.getTargetNames().stream())
                    .collect(Collectors.toList());
        }else{
            return Stream.of(StringUtils.split(reqContent, AssetConstants.KEY_DATA_REQ_SPLIT))
                    .map(KeyDataReqTargetRule::fromName)
                    .filter(Objects::nonNull)
                    .flatMap(rt->rt.getTargetNames().stream())
                    .collect(Collectors.toList());
        }
    }
}